package Gestor;

import Clases.Asignarprestamo;
import Clases.Prestamo;
import Control.ControlPago;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.hibernate.HibernateException;

public class GestorPrestamo extends GestorBase {

    private static GestorPrestamo instancia = null;
    private static final String PRESTAMO_CEDULA = "SP_SELECCIONAR_PRESTAMO_POR_CEDULA";
    private static final String PRESTAMO_CODIGO = "SP_SELECCIONAR_PRESTAMO_POR_CODIGO";
    private static final String PRESTAMOS_HISTORICOS = "SELECT alias.codigo FROM (SELECT sistemaplanilla.asignarprestamo.codigo FROM sistemaplanilla.asignarprestamo INNER JOIN sistemaplanilla.prestamo ON sistemaplanilla.asignarprestamo.codigo=sistemaplanilla.prestamo.codigo WHERE sistemaplanilla.prestamo.activo=1 AND sistemaplanilla.asignarprestamo.fechaPagoInicio>=:inicio AND sistemaplanilla.asignarprestamo.fechaPagoFin<=:fin )alias INNER JOIN sistemaplanilla.empleado ON sistemaplanilla.empleado.numEmpleado=:num AND sistemaplanilla.empleado.fechaFin is not null";

    public static GestorPrestamo obtenerInstancia() {
        if (instancia == null) {
            instancia = new GestorPrestamo();
        }
        return instancia;
    }

    private GestorPrestamo() {

    }

    //devuelve una lista de prestamos(con todos los atributos) donde los parametros, son los parametros
    //que se deben pasar al procedimiento almacena
    // y procedimiento es el nombre del procedimiento almacenado
    private ArrayList<Prestamo> getListaGenericaPrestamos(String procedimiento, ArrayList<Object> parametros) throws HibernateException {

        ArrayList<Prestamo> prestamos = new ArrayList<>();
        try {
            ResultSet rs = llamarProcedimientoAlmacenado(procedimiento, parametros);
            int maxCols = rs.getMetaData().getColumnCount();
            while (rs.next()) {
                ArrayList<Object> registro = new ArrayList<>(maxCols);
                for (int i = 0; i < maxCols; i++) {
                    registro.add(rs.getObject(i + 1));
                }
                prestamos.add(Prestamo.fromArray(registro));
            }

        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | SQLException e) {
            System.out.println(e.getMessage());
        } finally {
        }
        return prestamos;
    }

    public ArrayList<Prestamo> getPrestamosPorCodigoEmpleado(long codigo, Date fechaPagoInicio, Date fechaPagoFin) throws HibernateException {

        ArrayList<Object> parametros = new ArrayList<>();
        parametros.add(codigo);
        parametros.add(fechaPagoInicio);
        parametros.add(fechaPagoFin);
        return getListaGenericaPrestamos(PRESTAMO_CODIGO, parametros);
    }

    public ArrayList<Prestamo> getPrestamosPorCedula(long cedula, Date fechaPagoInicio, Date fechaPagoFin) throws HibernateException {

        ArrayList<Object> parametros = new ArrayList<>();
        parametros.add(cedula);
        parametros.add(fechaPagoInicio);
        parametros.add(fechaPagoFin);
        return getListaGenericaPrestamos(PRESTAMO_CEDULA, parametros);
    }

    public ArrayList<Prestamo> getListaPrestamos() throws HibernateException {
        ArrayList<Prestamo> listaPrestamos = null;
        try {
            iniciaOperacion();
            listaPrestamos = (ArrayList<Prestamo>) sesion.createQuery("from Prestamo WHERE activo=true").list();
        } finally {
            sesion.close();
        }
        return listaPrestamos;
    }

    public ArrayList<Prestamo> getListaPrestamosActuales() throws HibernateException {
        ArrayList<Prestamo> listaPrestamos = null;
        try {
            iniciaOperacion();
            listaPrestamos = (ArrayList<Prestamo>) sesion.createQuery("from Prestamo where deuda!=0 AND activo=true").list();
        } finally {
            sesion.close();
        }
        return listaPrestamos;
    }

    public boolean asignarPrestamoEmpleado(Object asignarPrestamo) {
        boolean verifica = false;
        try {
            iniciaOperacion();
            Object verificaAsignacion = sesion.createQuery("from Asignarprestamo where codigo= :?")
                    .setParameter("?", ((Asignarprestamo) asignarPrestamo).getPrestamo().getCodigo())
                    .uniqueResult();
            if (verificaAsignacion == null) {
                sesion.save(asignarPrestamo);
                tx.commit();
                verifica = true;
            } else {
                return false;//El codigo ya esta ocupado
            }
        } catch (HibernateException he) {
            System.out.println(he.getCause());
            System.out.println(he.getMessage());
            manejaExcepcion(he);
        } finally {
            sesion.close();
        }

        return verifica;
    }

    public int getUltimoIngresado() {
        int codigoUltimo = 0;
        try {
            iniciaOperacion();
            codigoUltimo = ((BigInteger) sesion.createSQLQuery("SELECT AUTO_INCREMENT FROM information_schema.Tables WHERE TABLE_SCHEMA='sistemaplanilla' AND table_name='prestamo'")
                    .uniqueResult()).intValue();
        } finally {
            sesion.close();
        }
        return codigoUltimo;
    }

    public ArrayList<java.math.BigInteger> getAsignacionPrestamo(long numEmpleado,java.sql.Date fechaPagoInicio) {
        ArrayList<java.math.BigInteger> listaAsignaciones = null;
        try {
            iniciaOperacion();
            
            listaAsignaciones = (ArrayList<java.math.BigInteger>) sesion.createSQLQuery("SELECT alias.codigo FROM (SELECT sistemaplanilla.asignarprestamo.codigo FROM sistemaplanilla.asignarprestamo INNER JOIN sistemaplanilla.prestamo ON sistemaplanilla.asignarprestamo.codigo=sistemaplanilla.prestamo.codigo WHERE sistemaplanilla.prestamo.activo=1 AND sistemaplanilla.asignarprestamo.numEmpleado=:num and sistemaplanilla.asignarprestamo.fechaPagoInicio=:fecha)alias")
                    .setParameter("num", numEmpleado)
                    .setParameter("fecha", fechaPagoInicio)
                    .list();
        } finally {
            sesion.close();
        }
        return listaAsignaciones;
    }

    public Prestamo getPrestamoPorCodigo(int codigo) throws HibernateException {
        Prestamo prestamo = null;
        try {
            iniciaOperacion();
            prestamo = (Prestamo) sesion.get(Prestamo.class, codigo);
        } finally {
            sesion.close();
        }

        return prestamo;
    }

    public ArrayList<java.math.BigInteger> getAsignacionPrestamoHistoricos(Long numEmpleado, Date fechaPagoInicio, Date fechaPagoFin) {
        ArrayList<java.math.BigInteger> listaAsignaciones = null;
        try {
            iniciaOperacion();
            listaAsignaciones = (ArrayList<java.math.BigInteger>) sesion.createSQLQuery(PRESTAMOS_HISTORICOS)
                    .setParameter("inicio", fechaPagoInicio)
                    .setParameter("fin", fechaPagoFin)
                    .setParameter("num", numEmpleado)
                    .list();
        } finally {
            sesion.close();
        }
        return listaAsignaciones;
    }
}
